package com.mega.center.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mega.center.system.mapper.DictionaryDataMapper;
import com.mega.center.system.model.entity.DictionaryData;
import com.mega.center.system.model.vo.DictionaryDataVO;
import com.mega.center.system.service.IDictionaryDataService;
import com.mega.common.core.constant.CacheConstants;
import com.mega.common.core.enums.CommonMsgEnum;
import com.mega.common.core.enums.CommonStatus;
import com.mega.common.core.exception.BusinessException;
import com.mega.common.core.web.service.MegaBaseServiceImpl;
import com.mega.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 字典数据  服务实现
 *
 * @author Eric
 * @version 1.0
 * @since 2020-09-28
 */
@Service
@Slf4j
public class DictionaryDataServiceImpl extends MegaBaseServiceImpl<DictionaryDataMapper, DictionaryData> implements IDictionaryDataService {

    @Autowired
    private RedisService redisService;

    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        this.refresh();
        log.info("字典数据初始化成功...");
    }

    /**
     * 新增字典数据
     *
     * @param dictionaryData 字典数据 实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(DictionaryData dictionaryData) {
        Integer nameCount = this.count(Wrappers.<DictionaryData>lambdaQuery()
                .eq(DictionaryData::getDictCode, dictionaryData.getDictCode())
                .eq(DictionaryData::getDataLabel, dictionaryData.getDataLabel()));
        if (nameCount != null && nameCount > 0) {
            throw new BusinessException(CommonMsgEnum.NAME_REPEAT, dictionaryData.getDataLabel());
        }
        //判断名称是否重复
        Integer valueCount = this.count(Wrappers.<DictionaryData>lambdaQuery()
                .eq(DictionaryData::getDictCode, dictionaryData.getDictCode())
                .eq(DictionaryData::getDataValue, dictionaryData.getDataValue()));
        if (valueCount != null && valueCount > 0) {
            throw new BusinessException(CommonMsgEnum.CODE_REPEAT, dictionaryData.getDataValue());
        }
        //插入数据
        this.save(dictionaryData);
    }

    /**
     * 编辑字典数据
     *
     * @param dictionaryData 字典数据 实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DictionaryData dictionaryData) {
        //判断数据是否为空
        DictionaryData queryEntity = this.getById(dictionaryData.getId());
        if (queryEntity == null) {
            throw new BusinessException(CommonMsgEnum.DATE_NOT_EXIST);
        }
        //查询修改后名称是否与原先一致
        if (!dictionaryData.getDataLabel().equals(queryEntity.getDataLabel())) {
            //判断名称是否重复
            Integer nameCount = this.count(Wrappers.<DictionaryData>lambdaQuery()
                    .eq(DictionaryData::getDictCode, dictionaryData.getDictCode())
                    .eq(DictionaryData::getDataLabel, dictionaryData.getDataLabel()));
            if (nameCount != null && nameCount > 0) {
                throw new BusinessException(CommonMsgEnum.NAME_REPEAT, dictionaryData.getDataLabel());
            }
        }

        //查询修改后值是否与原先一致
        if (!dictionaryData.getDataValue().equals(queryEntity.getDataValue())) {
            //判断名称是否重复
            Integer valueCount = this.count(Wrappers.<DictionaryData>lambdaQuery()
                    .eq(DictionaryData::getDictCode, dictionaryData.getDictCode())
                    .eq(DictionaryData::getDataValue, dictionaryData.getDataValue()));
            if (valueCount != null && valueCount > 0) {
                throw new BusinessException(CommonMsgEnum.CODE_REPEAT, dictionaryData.getDataValue());
            }
        }
        //更新数据
        this.updateById(dictionaryData);
    }

    /**
     * 根据id删除字典数据
     *
     * @param id 主键值
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Integer id) {
        this.removeById(id);
    }

    /**
     * 根据字典编码查询字典数据
     *
     * @param dictCode
     * @return
     */
    @Override
    public List<DictionaryData> listDetailByDictCode(String dictCode) {
        return this.list(Wrappers.<DictionaryData>lambdaQuery().eq(DictionaryData::getDictCode, dictCode).orderByAsc(DictionaryData::getDataOrder));
    }

    /**
     * 根据字典编码查询字典数据:下拉
     *
     * @param dictCode
     * @return
     */
    @Override
    public List<DictionaryDataVO> listByDictCode(String dictCode) {
        String key = CacheConstants.DICTIONARY + dictCode;
        if (redisService.hasKey(key)) {
            return redisService.getCacheList(key);
        } else {
            List<DictionaryDataVO> dataVOList = Optional.ofNullable(this.listDetailByDictCode(dictCode)).map(list ->
                    list.stream().filter(v -> CommonStatus.NORMAL.getCode().equals(v.getDataStatus()))
                            .map(data -> new DictionaryDataVO(data.getDataLabel(), data.getDataValue()))
                            .collect(Collectors.toList())).orElse(null);
            redisService.setCacheList(key, dataVOList);
            return dataVOList;
        }
    }

    /**
     * 刷新缓存
     */
    @Override
    public void refresh() {
        redisService.deleteObject(redisService.keys(CacheConstants.DICTIONARY + "*"));
        List<DictionaryData> dictionaryDataList = this.baseMapper.listValidDictionaryData();
        if (CollectionUtil.isNotEmpty(dictionaryDataList)) {
            Map<String, List<DictionaryData>> dictionaryDataMap = dictionaryDataList.stream().collect(Collectors.groupingBy(DictionaryData::getDictCode));
            dictionaryDataMap.forEach((k, v) -> {
                List<DictionaryDataVO> dataList = v.stream().map(data -> new DictionaryDataVO(data.getDataLabel(), data.getDataValue())).collect(Collectors.toList());
                redisService.setCacheList(CacheConstants.DICTIONARY + k, dataList);
            });
        }
    }
}
